PXII.LIB
A library for parsing using parser combinators, with DEFs for hierarchical objects to create parsers and receive results. ( also JSON support as an example of parser combinators! )
Japanese wiki page:
http://wiki.hosiken.jp/petc4/?Toukou%2FPXLIB
Instructions:
Define a parser with
PXDEFPC. Parser names start with
@.
PXDEFPC @_SPACE,REGEXP("[\x20]*")
PXDEFPC @EXPR,ACTP(LISTP(@TERM,CHARP("+-")),"0:ONCALCB")
PXDEFPC @TERM,ACTP(LISTP(@FACT,CHARP("*/%")),"0:ONCALCB")
PXDEFPC @FACT,ACTP(SEQP(REGEXP("[-]*"),ORP(@REAL,SEQP("(",@EXPR,")"))),"0:ONFACT")
PXDEFPC @REAL,REGEXP("([0-9]+(\.[0-9]*)?|[0-9]*\.[0-9]+)")
The reserved name
@_SPACE indicates a skip parser.
Pass the source, start position, and parser to
PXPARSE to parse. The results are returned as an object.
DIM RES=PXPARSE("3*(6-2)",0,@EXPR)
Use
OBJGET to get the value by key.
DIM SUCCESS=OBJGET(RES,"SUCCESS")
DIM POS=OBJGET(RES,"POS")
IF SUCCESS THEN
DIM VALUE=OBJGET(RES,"VALUE")
' VALUE should be 12 in this case.
' The key "VALUE" is generated by the custom actions, ONCALCB and ONFACT.
ENDIF
Notes:
äž: į°ĄåãĒč¨įŽæŠ
Example: Simple calculator
OPTION STRICT
ACLS
LOAD "PXIILIB-0.3.0/PXII.LIB",1
EXEC 1
INITPC
LOOP
LINPUT "?";EXPR
PRINT "=";EVAL(EXPR)
ENDLOOP
DEF INITPC
PXDEFPC @_SPACE,REGEXP("[\x20]*")
PXDEFPC @EXPR,ACTP(LISTP(@TERM,CHARP("+-")),"0:ONCALCB")
PXDEFPC @TERM,ACTP(LISTP(@FACT,CHARP("*/%")),"0:ONCALCB")
PXDEFPC @FACT,ACTP(SEQP(REGEXP("[-]*"),ORP(@REAL,SEQP("(",@EXPR,")"))),"0:ONFACT")
PXDEFPC @REAL,REGEXP("([0-9]+(\.[0-9]*)?|[0-9]*\.[0-9]+)")
END
DEF EVAL(EXPR)
DIM RES=PXPARSE(EXPR,0,@EXPR)
IF OBJGET(RES,"SUCCESS") THEN
RETURN OBJGET(RES,"VALUE")
ELSE
RETURN POW(2,1024)*0 'nan
ENDIF
END
DEF ONFACT RES
DIM SIGN=1-(LEN(OBJGET(RES,"SEQ0.BUFF")) MOD 2)*2
DIM BUFF=OBJGET(RES,"SEQ1.BUFF")
IF LEFT$(BUFF,1)=="(" THEN
OBJSET RES,"VALUE",SIGN*OBJGET(RES,"SEQ1.SEQ1.VALUE")
ELSE
OBJSET RES,"VALUE",SIGN*VAL(BUFF)
ENDIF
END
DEF ONCALCB RES
DIM I,O,A,B
A=OBJGET(RES,"LISTSUB0.VALUE")
FOR I=1 TO OBJGET(RES,"LIST#")-1
O=OBJGET(RES,"LISTDEL"+STR$(I-1)+".BUFF")
B=OBJGET(RES,"LISTSUB"+STR$(I)+".VALUE")
A=CALCB(O,A,B)
NEXT
OBJSET RES,"VALUE",A
END
DEF CALCB(O,A,B)
CASE O
WHEN "+":RETURN A+B
WHEN "-":RETURN A-B
WHEN "*":RETURN A*B
WHEN "/":RETURN A/B
WHEN "%":RETURN A MOD B
ENDCASE
END