o
    ÞhjÒH  ã                   @  sî   d Z ddlmZ ddlmZmZmZmZmZm	Z	m
Z
mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z# ddl$m%Z%m&Z& h d£Z'h d£Z(G dd	„ d	e)ƒZ*ddd„Z+G dd„ dƒZ,ddd„Z-dS )aÛ  Recursive-descent parser for MicroBasic.

Grammar and precedence follow the confirmed evidence in
docs/reverse_engineering.md, not just the manual's prose (which doesn't
state operator precedence explicitly). Precedence, loosest to tightest
binding -- confirmed by decoding real compiled output, not assumed:

    Or / XOr
    And
    Not                     (unary; confirmed to bind tighter than And)
    relational: = <> < > <= <=
    shift: << >>
    additive: + -
    multiplicative: * / Mod
    unary -                 (confirmed: unary + does not compile at all --
                              RoborunPlus itself rejects it)
    postfix ++ --
    primary (literals, var refs incl. array index, calls, parens,
              prefix ++/--)

Compound assignment (+=, -=, *=, /=, <<=, >>=) is desugared here into a
plain '=' with a synthesized BinaryOp RHS, since that's confirmed to be
exactly how the real compiler treats it -- codegen.py never sees a compound
assignment operator.
é    )Úannotationsé   ) Ú
AssignStmtÚBinaryOpÚBoolLiteralÚCallÚContinueStmtÚDimStmtÚDoLoopUntilStmtÚDoLoopWhileStmtÚDoUntilStmtÚExitStmtÚExprÚExprStmtÚForCStyleStmtÚForTraditionalStmtÚ	GosubStmtÚGotoStmtÚIfStmtÚ
IncDecExprÚ
IncDecStmtÚ
IntLiteralÚLabelÚOptionExplicitStmtÚ	PrintStmtÚProgramÚ
ReturnStmtÚStmtÚStringLiteralÚTerminateStmtÚUnaryOpÚVarRefÚWaitStmtÚ	WhileStmt)ÚTokenÚ	TokenType>   ú*=ú+=ú-=ú/=ú<<=ú>>=ú=>   ú<=ú<>ú>=ú<r,   ú>c                      s   e Zd Zd‡ fdd„Z‡  ZS )Ú
ParseErrorÚmessageÚstrÚtokenr$   c                   s    t ƒ  |› d|›¡ || _d S )Nz at )ÚsuperÚ__init__r5   )Úselfr3   r5   ©Ú	__class__© úM/sessions/nice-awesome-ritchie/mnt/compiler/src/microbasic_compiler/parser.pyr7   F   s   
zParseError.__init__)r3   r4   r5   r$   )Ú__name__Ú
__module__Ú__qualname__r7   Ú__classcell__r;   r;   r9   r<   r2   E   s    r2   Útextr4   ÚreturnÚintc                 C  s:   |   ¡ }| d¡rt| dƒS | d¡rt| dƒS t| dƒS )NÚ0xé   Ú0bé   é
   )ÚlowerÚ
startswithrC   )rA   Úlowr;   r;   r<   Úparse_int_literalK   s   




rL   c                   @  s°  e Zd Zdxdd„Zdydd„Zdzd
d„Zd{dd„Zdzdd„Zd|dd„Zd}dd„Z	d~dd„Z
ddd„Zd€d d!„Zdd#d$„Zd‚d&d'„Zdƒd+d,„Zd„d.d/„Zd…d1d2„Zd†d4d5„Zd‡d7d8„Zdˆd:d;„Zd„d<d=„Zd„d>d?„Zd‰dAdB„ZdŠdDdE„Zd‹dGdH„ZdŒdJdK„ZddMdN„ZdŽdPdQ„ZddSdT„ZddUdV„Zd„dWdX„Zd‘dZd[„Z d’d^d_„Z!d“dadb„Z"d“dcdd„Z#d“dedf„Z$d“dgdh„Z%d“didj„Z&d“dkdl„Z'd“dmdn„Z(d“dodp„Z)d“dqdr„Z*d“dsdt„Z+d“dudv„Z,dwS )”ÚParserÚtokensúlist[Token]c                 C  s   || _ d| _d S )Nr   ©rN   Úpos)r8   rN   r;   r;   r<   r7   U   s   
zParser.__init__rB   r   c                 C  s   | j tƒ d}t|dS )N)Úterminators)Ú
statements)Úparse_blockÚsetr   )r8   rS   r;   r;   r<   ÚparseY   s   
zParser.parser$   c                 C  s   | j | j S ©NrP   ©r8   r;   r;   r<   Ú_peek_   ó   zParser._peekÚboolc                 C  s   |   ¡ jtjkS rW   )rY   Útyper%   ÚEOFrX   r;   r;   r<   Ú_at_endb   s   zParser._at_endc                 C  s&   | j | j }|  ¡ s|  jd7  _|S )Nr   )rN   rQ   r^   )r8   Útokr;   r;   r<   Ú_advancee   s   zParser._advanceÚtype_r%   c                 C  s   |   ¡ j|kS rW   )rY   r\   )r8   ra   r;   r;   r<   Ú_checkk   s   zParser._checkÚvaluesr4   c                 G  ó   |   tj¡o|  ¡ j|v S rW   )rb   r%   ÚOPrY   Úvalue)r8   rc   r;   r;   r<   Ú	_check_opn   ó   zParser._check_opÚwordsc                 G  rd   rW   )rb   r%   ÚKEYWORDrY   rf   )r8   ri   r;   r;   r<   Ú_check_keywordq   rh   zParser._check_keywordr3   c                 C  s    |   |¡st||  ¡ ƒ‚|  ¡ S rW   )rb   r2   rY   r`   )r8   ra   r3   r;   r;   r<   Ú_expectt   s   
zParser._expectÚwordc                 C  ó(   |   |¡std|› d|  ¡ ƒ‚|  ¡ S ©Nz
expected 'ú')rk   r2   rY   r`   )r8   rm   r;   r;   r<   Ú_expect_keywordy   ó   
zParser._expect_keywordrf   c                 C  rn   ro   )rg   r2   rY   r`   )r8   rf   r;   r;   r<   Ú
_expect_op~   rr   zParser._expect_opÚNonec                 C  s(   |   tj¡r|  ¡  |   tj¡sd S d S rW   )rb   r%   ÚNEWLINEr`   rX   r;   r;   r<   Ú_skip_newlinesƒ   s   ÿzParser._skip_newlinesrR   úset[str]ú
list[Stmt]c                 C  s@   g }	 |   ¡  |  ¡ r	 |S |r| j|Ž r	 |S | |  ¡ ¡ qrW   )rv   r^   rk   ÚappendÚparse_statement)r8   rR   Ústmtsr;   r;   r<   rT   ‰   s   ýÿúzParser.parse_blockr   c                 C  sˆ   |   tj¡r|  ¡ }t|jƒS |   tj¡r@|  ¡ j}| j| j	| j
| j| j| j| j| j| j| j| j| j| jdœ}||v r@|| ƒ S |  ¡ S )N)ÚdimÚoptionÚifÚwhileÚdoÚforÚgotoÚgosubrB   Ú	terminateÚprintÚexitÚcontinue)rb   r%   ÚLABELr`   r   rf   rj   rY   Ú	parse_dimÚparse_option_explicitÚparse_ifÚparse_whileÚparse_doÚ	parse_forÚ
parse_gotoÚparse_gosubÚparse_returnÚparse_terminateÚparse_printÚ
parse_exitÚparse_continueÚparse_simple_statement)r8   r_   ÚkwÚdispatchr;   r;   r<   rz   ”   s,   

ó
zParser.parse_statementr	   c                 C  sª   |   ¡  |  tjd¡}d }|  tj¡r*|   ¡  |  tjd¡}t|jƒ}|  tj	d¡ |  
d¡ |  d¡r;|   ¡  d}n|  d¡rG|   ¡  d}ntd	|  ¡ ƒ‚t|j||ƒS )
Nz expected variable name after Dimzexpected array lengthúexpected ']'ÚasÚintegerÚIntegerÚbooleanÚBooleanzexpected 'Integer' or 'Boolean')r`   rl   r%   ÚIDENTrb   ÚLBRACKETÚINTEGERrL   rf   ÚRBRACKETrq   rk   r2   rY   r	   )r8   Úname_tokÚ	array_lenÚlen_tokÚvar_typer;   r;   r<   r‰   ¯   s"   



zParser.parse_dimr   c                 C  s   |   ¡  |  d¡ tƒ S )NÚexplicit)r`   rq   r   rX   r;   r;   r<   rŠ   Ã   s   
zParser.parse_option_explicitr   c                 C  s.  |   ¡  |  ¡ }|  d¡r|   ¡  |  tj¡s|  ¡ r{|  ¡  |  h d£¡}g }|  d¡rU|   ¡  |  ¡ }|  d¡r>|   ¡  |  ¡  |  h d£¡}| 	||f¡ |  d¡s-d }|  d¡rj|   ¡  |  ¡  |  dh¡}|  
d¡ |  
d¡ t||||ƒS |  ¡ }d }|  d¡r|   ¡  |  ¡ g}t||gg |ƒS )NÚthen>   ÚendÚelseÚelseifr«   rª   r©   r~   )r`   Úparse_expressionrk   rb   r%   ru   r^   rv   rT   ry   rq   r   rz   )r8   Ú	conditionÚ
then_blockÚelseif_clausesÚcond2Úbody2Ú
else_blockÚ	then_stmtr;   r;   r<   r‹   È   s>   



ù




zParser.parse_ifr#   c                 C  sB   |   ¡  |  ¡ }|  ¡  |  dh¡}|  d¡ |  d¡ t||ƒS )Nr©   r   )r`   r¬   rv   rT   rq   r#   ©r8   r­   Úbodyr;   r;   r<   rŒ   ì   s   


zParser.parse_whilec                 C  s   |   ¡  |  d¡r%|   ¡  |  ¡ }|  ¡  |  dh¡}|  d¡ t||ƒS |  d¡rF|   ¡  |  ¡ }|  ¡  |  dh¡}|  d¡ t||ƒS |  ¡  |  dh¡}|  d¡ |  d¡rg|   ¡  |  ¡ }t||ƒS |  d¡ry|   ¡  |  ¡ }t	||ƒS t
d|  ¡ ƒ‚)Nr   ÚloopÚuntilz(expected 'While' or 'Until' after 'Loop')r`   rk   r¬   rv   rT   rq   r#   r   r   r
   r2   rY   r´   r;   r;   r<   r   õ   s6   










zParser.parse_doc                 C  s.  |   ¡  |  tjd¡}|  d¡ |  ¡ }|  d¡rR|   ¡  |  ¡ }d }|  d¡r0|   ¡  |  ¡ }|  ¡  |  dh¡}|  	d¡ |  
tj¡rI|   ¡  t|j||||ƒS |  d¡r|   ¡  |  ¡ }d }|  d¡rn|   ¡  |  ¡ }|  ¡  |  dh¡}|  	d¡ |  
tj¡r‡|   ¡  t|j||||ƒS td|  ¡ ƒ‚)	Nzexpected loop variable namer,   ÚtoÚstepÚnextÚandwhileÚevaluatez,expected 'To' or 'AndWhile' in For statement)r`   rl   r%   rŸ   rs   r¬   rk   rv   rT   rq   rb   r   rf   r–   r   r2   rY   )r8   Úvar_tokÚinitÚlimitr¹   rµ   r­   r¼   r;   r;   r<   rŽ     s>   






zParser.parse_forr   c                 C  ó    |   ¡  |  tjd¡}t|jƒS )Nzexpected label name after GoTo)r`   rl   r%   rŸ   r   rf   ©r8   Ú	label_tokr;   r;   r<   r   9  ó   
zParser.parse_gotor   c                 C  rÀ   )Nzexpected label name after GoSub)r`   rl   r%   rŸ   r   rf   rÁ   r;   r;   r<   r   >  rÃ   zParser.parse_gosubr   c                 C  ó   |   ¡  tƒ S rW   )r`   r   rX   r;   r;   r<   r‘   C  ó   zParser.parse_returnr   c                 C  rÄ   rW   )r`   r   rX   r;   r;   r<   r’   G  rÅ   zParser.parse_terminater   c                 C  s4   |   ¡  |  tjd¡ |  ¡ }|  tjd¡ t|ƒS )Nzexpected '(' after Printúexpected ')')r`   rl   r%   ÚLPARENÚ_parse_arg_listÚRPARENr   ©r8   Úargsr;   r;   r<   r“   K  s
   zParser.parse_printr   c                 C  ó   |   ¡  t|  ¡ ƒS rW   )r`   r   Ú_expect_loop_kindrX   r;   r;   r<   r”   R  ó   zParser.parse_exitr   c                 C  rÌ   rW   )r`   r   rÍ   rX   r;   r;   r<   r•   V  rÎ   zParser.parse_continuec                 C  s6   dD ]\}}|   |¡r|  ¡  |  S qtd|  ¡ ƒ‚)N))r   ÚFor)r   ÚWhile)r€   ÚDoz expected 'For', 'While', or 'Do')rk   r`   r2   rY   )r8   r—   Úkindr;   r;   r<   rÍ   Z  s   
þzParser._expect_loop_kindc           
      C  s‚  |   dd¡r|  ¡ j}|  tjd¡}t|j|ƒS |  tj¡rº|  ¡ }|  tj¡rL|  	|j¡}|j 
¡ dkrHt|jƒdkrAtd|ƒ‚t|jd ƒS t|ƒS |   dd¡r]|  ¡ j}t|j|ƒS d }|  tj¡rt|  ¡  |  ¡ }|  tjd¡ |  tj¡r®|  ¡ jtv r®|  ¡ j}|  ¡ }t|j|ƒ}|d	kr™t||ƒS |d d
… }t|t|j|ƒ|ƒ}	t||	ƒS td|j› d|  ¡ ƒ‚td|  ¡ ƒ‚)Nú++ú--úexpected variable nameÚwaitr   zWait expects exactly 1 argumentr   r™   r,   éÿÿÿÿzunexpected token after 'rp   zexpected a statement)rg   r`   rf   rl   r%   rŸ   r   rb   rÇ   Ú_parse_callrI   ÚlenrË   r2   r"   r   r    r¬   r¢   re   rY   Ú
ASSIGN_OPSr!   r   r   )
r8   Úopr£   r_   ÚcallÚindexrf   ÚtargetÚbinopÚ	desugaredr;   r;   r<   r–   a  s@   





zParser.parse_simple_statementú
list[Expr]c                 C  sP   g }|   tj¡s&| |  ¡ ¡ |   tj¡r&|  ¡  | |  ¡ ¡ |   tj¡s|S rW   )rb   r%   rÉ   ry   r¬   ÚCOMMAr`   rÊ   r;   r;   r<   rÈ   ‹  s   þzParser._parse_arg_listÚnamer   c                 C  s.   |   tjd¡ |  ¡ }|   tjd¡ t||ƒS )Nzexpected '('rÆ   )rl   r%   rÇ   rÈ   rÉ   r   )r8   rã   rË   r;   r;   r<   rØ   ”  s   
zParser._parse_callr   c                 C  s   |   ¡ S rW   )Úparse_orrX   r;   r;   r<   r¬   œ  s   zParser.parse_expressionc                 C  óB   |   ¡ }|  dd¡r|  ¡ j}|   ¡ }t|||ƒ}|  dd¡s
|S )NÚorÚxor)Ú	parse_andrk   r`   rf   r   ©r8   ÚleftrÛ   Úrightr;   r;   r<   rä   Ÿ  ó   
ýzParser.parse_orc                 C  s<   |   ¡ }|  d¡r|  ¡  |   ¡ }td||ƒ}|  d¡s	|S )NÚand)Ú	parse_notrk   r`   r   )r8   rê   rë   r;   r;   r<   rè   §  s   

ýzParser.parse_andc                 C  ó(   |   d¡r|  ¡  td|  ¡ ƒS |  ¡ S )NÚnot)rk   r`   r    rî   Úparse_relationalrX   r;   r;   r<   rî   ¯  ó   
zParser.parse_notc                 C  s^   |   ¡ }|  tj¡r-|  ¡ jtv r-|  ¡ j}|   ¡ }t|||ƒ}|  tj¡r-|  ¡ jtv s|S rW   )	Úparse_shiftrb   r%   re   rY   rf   ÚRELATIONAL_OPSr`   r   ré   r;   r;   r<   rñ   µ  s   
ýzParser.parse_relationalc                 C  rå   )Nz<<z>>)Úparse_additiverg   r`   rf   r   ré   r;   r;   r<   ró   ½  rì   zParser.parse_shiftc                 C  rå   )Nú+ú-)Úparse_multiplicativerg   r`   rf   r   ré   r;   r;   r<   rõ   Å  rì   zParser.parse_additivec                 C  sV   |   ¡ }|  dd¡s|  d¡r)|  ¡ j}|   ¡ }t|||ƒ}|  dd¡s|  d¡s|S )NÚ*ú/Úmod)Úparse_unaryrg   rk   r`   rf   r   ré   r;   r;   r<   rø   Í  s   
ýzParser.parse_multiplicativec                 C  rï   )Nr÷   )rg   r`   r    rü   Úparse_postfixrX   r;   r;   r<   rü   Õ  rò   zParser.parse_unaryc                 C  sT   |   ¡ }|  dd¡r(|  ¡ j}t|tƒr|jd ur td|  ¡ ƒ‚t	|j
|ddS |S )NrÓ   rÔ   z-'++'/'--' can only apply to a simple variableF©Úprefix)Úparse_primaryrg   r`   rf   Ú
isinstancer!   rÝ   r2   rY   r   rã   )r8   ÚexprrÛ   r;   r;   r<   rý   Û  s   
zParser.parse_postfixc                 C  s˜  |   ¡ }|  dd¡r|  ¡ j}|  tjd¡}t|j|ddS |  tj	¡r/|  ¡  t
t|jƒƒS |  tj¡r>|  ¡  t|jƒS |  d¡rK|  ¡  tdƒS |  d¡rX|  ¡  tdƒS |  d	¡ry|  ¡  |  tjd
¡ |  ¡ }|  tjd¡ td	|gƒS |  tj¡r|  ¡  |  ¡ }|  tjd¡ |S |  tj¡rÃ|  ¡  |  tj¡r¦|  |j¡S d }|  tj¡r½|  ¡  |  ¡ }|  tjd¡ t|j|ƒS td|›d|ƒ‚)NrÓ   rÔ   rÕ   Trþ   ÚtrueÚfalseFÚtoboolzexpected '(' after ToBoolrÆ   r™   zunexpected token z in expression)rY   rg   r`   rf   rl   r%   rŸ   r   rb   r¡   r   rL   ÚSTRINGr   rk   r   rÇ   r¬   rÉ   r   rØ   r    r¢   r!   r2   )r8   r_   rÛ   r£   ÚinnerrÝ   r;   r;   r<   r   ä  sN   




zParser.parse_primaryN)rN   rO   )rB   r   )rB   r$   )rB   r[   )ra   r%   rB   r[   )rc   r4   rB   r[   )ri   r4   rB   r[   )ra   r%   r3   r4   rB   r$   )rm   r4   rB   r$   )rf   r4   rB   r$   )rB   rt   )rR   rw   rB   rx   )rB   r   )rB   r	   )rB   r   )rB   r   )rB   r#   )rB   r   )rB   r   )rB   r   )rB   r   )rB   r   )rB   r   )rB   r   )rB   r4   )rB   rá   )rã   r4   rB   r   )rB   r   )-r=   r>   r?   r7   rV   rY   r^   r`   rb   rg   rk   rl   rq   rs   rv   rT   rz   r‰   rŠ   r‹   rŒ   r   rŽ   r   r   r‘   r’   r“   r”   r•   rÍ   r–   rÈ   rØ   r¬   rä   rè   rî   rñ   ró   rõ   rø   rü   rý   r   r;   r;   r;   r<   rM   T   sV    

















$
	
 
$








*
	









	rM   rN   rO   r   c                 C  s   t | ƒ ¡ S rW   )rM   rV   )rN   r;   r;   r<   rV     rZ   rV   N)rA   r4   rB   rC   )rN   rO   rB   r   ).Ú__doc__Ú
__future__r   Ú	ast_nodesr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   rN   r$   r%   rÚ   rô   Ú	Exceptionr2   rL   rM   rV   r;   r;   r;   r<   Ú<module>   s    ˆ"
	   F