ParserReturn parse(const std::string &s) { Lexer l(s); LexerReturn r(l.get()); switch (r.type()) { case L_EOF: return ParserReturn(L_EOF); case KW_Break: if (l.get().type() != KW_At) return ParserReturn(P_Error); r = l.get(); if (!r.is_integer() || l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(KW_Break, r); case KW_Exit: case KW_Clear: if (l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(r); case KW_Print_Insns: r = l.get(); if (r.type() == L_EOF) return ParserReturn(KW_Print_Insns); else if (!r.is_integer() || l.get().type() != L_EOF) return ParserReturn(P_Error); else return ParserReturn(KW_Print_Insns, r); case KW_Help: case L_QuestionMark: if (l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(KW_Help); case KW_Delete: r = l.get(); if (!r.is_integer() || l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(KW_Delete, r); case KW_Load: case KW_Read: case KW_Compile: { LexerReturn s(l.get()); if (s.type() == L_EOF) return ParserReturn(r); else if (!s.is_string() || l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(r, s); } /*NOTREACHED*/ case KW_Run: { bool set_at = false; bool set_for = false; Integer at_val, for_val; for (;;) { r = l.get(); if (r.type() == L_EOF) break; if (r.type() == KW_At && !set_at) { r = l.get(); if (!r.is_integer()) return ParserReturn(P_Error); set_at = true; at_val = r.get_integer(); } else if (r.type() == KW_For && !set_for) { r = l.get(); if (!r.is_integer()) return ParserReturn(P_Error); set_for = true; for_val = r.get_integer(); } else return ParserReturn(P_Error); } return ParserReturn(KW_Run, (set_at ? LexerReturn(at_val) : LexerReturn(P_Missing)), (set_for ? LexerReturn(for_val) : LexerReturn(P_Missing)) ); } /*NOTREACHED*/ case KW_Set: r = l.get(); switch (r.type()) { case KW_Cell: { LexerReturnType t_length(P_Missing), t_signed(P_Missing); LexerReturnType tp; for (;;) { if ((tp = l.get().type()) == L_EOF) break; switch (tp) { case KW_Int: break; case KW_Char: case KW_Short: case KW_Long: if (t_length != P_Missing) return ParserReturn(P_Error); t_length = tp; break; case KW_Signed: case KW_Unsigned: if (t_signed != P_Missing) return ParserReturn(P_Error); t_signed = tp; break; default: return ParserReturn(P_Error); break; } } return ParserReturn(KW_Set, KW_Cell, t_signed, t_length); } break; case KW_Default: if (l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(KW_Set, r); case KW_Position: case KW_PC: { LexerReturnType tp = r.type(); r = l.get(); if (!r.is_integer() || l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(KW_Set, tp, r); } /*NOTREACHED*/ case KW_Tape: { r = l.get(); if (!r.is_integer()) return ParserReturn(P_Error); LexerReturn s = l.get(); if (!s.is_integer()) return ParserReturn(P_Error); return ParserReturn(KW_Set, KW_Tape, r, s); } /*NOTREACHED*/ case KW_Low: case KW_High: case KW_Left: case KW_Right: { LexerReturnType tp = r.type(); r = l.get(); if (r.type() != KW_Wraparound && r.type() != KW_Limiting && r.type() != KW_Abort && r.type() != KW_Undefined && r.type() != KW_Infinite && r.type() != L_Integer) return ParserReturn(P_Error); LexerReturn s(l.get()); if (s.type() == L_EOF) return ParserReturn(KW_Set, tp, r); if (r.type() == KW_Infinite) return ParserReturn(P_Error); if (r.type() == L_Integer) { if (s.type() != KW_Wraparound && s.type() != KW_Limiting && s.type() != KW_Abort && s.type() != KW_Undefined) return ParserReturn(P_Error); else if (l.get().type() != L_EOF) return ParserReturn(P_Error); else return ParserReturn(KW_Set, tp, r, s); } else { if (s.type() != L_Integer) return ParserReturn(P_Error); else if (l.get().type() != L_EOF) return ParserReturn(P_Error); else return ParserReturn(KW_Set, tp, s, r); } } /*NOTREACHED*/ case KW_Input: r = l.get(); if (r.type() != KW_Signed && r.type() != KW_Unsigned && r.type() != KW_Char && r.type() != KW_Decimal) return ParserReturn(P_Error); if (r.type() == KW_Signed || r.type() == KW_Unsigned) { LexerReturn s = l.get(); if (s.type() == KW_Char) { if (l.get().type() != L_EOF) return ParserReturn(P_Error); } else if (s.type() != L_EOF) return ParserReturn(P_Error); } else if (l.get().type() != L_EOF) return ParserReturn(P_Error); if (r.type() == KW_Char) return ParserReturn(KW_Set, KW_Input, LexerReturn(KW_Unsigned)); else return ParserReturn(KW_Set, KW_Input, r); /*NOTREACHED*/ case KW_Eof: r = l.get(); if (r.type() == KW_Value) { r = l.get(); if (r.type() != L_Integer) return ParserReturn(P_Error); } else if (r.type() != L_Integer && r.type() != KW_Nop && r.type() != KW_Halt && r.type() != KW_Abort && r.type() != KW_Value) return ParserReturn(P_Error); if (l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(KW_Set, KW_Eof, r); case KW_Output: r = l.get(); if (r.type() != KW_Char && r.type() != KW_Decimal) return ParserReturn(P_Error); if (l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(KW_Set, KW_Output, r); default: return ParserReturn(P_Error); } /*NOTREACHED*/ case KW_Show: r = l.get(); switch (r.type()) { case L_EOF: return ParserReturn(KW_Show); case KW_Copying: case KW_Warranty: if (l.get().type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(KW_Show, r); case KW_Prog: case KW_Tape: { LexerReturnType tp = r.type(); bool set_num = false; bool set_at = false; Integer num_val, at_val; r = l.get(); if (r.is_integer()) { set_num = true; num_val = r.get_integer(); r = l.get(); } if (r.type() == KW_At) { r = l.get(); if (!r.is_integer()) return ParserReturn(P_Error); set_at = true; at_val = r.get_integer(); r = l.get(); } if (r.type() != L_EOF) return ParserReturn(P_Error); return ParserReturn(KW_Show, tp, (set_num ? LexerReturn(num_val) : LexerReturn(P_Missing)), (set_at ? LexerReturn(at_val) : LexerReturn(P_Missing)) ); } /*NOTREACHED*/ default: return ParserReturn(P_Error); } /*NOTREACHED*/ default: return ParserReturn(P_Error); } /*NOTREACHED*/ }