Remove skipchar, add stdinlineno / stdincolno
With the new check function, this helper method doesn't make much sense to put in the standard library. To replicate the same result, we do need to expose the current line number; adding column number is a nice bonus. Also; made it a bit clearer when a check failes in it2. Also; the builtincheckfalse was not working. Also; separated out the test input file to have more data.
This commit is contained in:
parent
ed09d37213
commit
2eaa763a2c
@ -39,11 +39,6 @@ def skip():
|
||||
|
||||
PEEK = None
|
||||
|
||||
def skipchar(char):
|
||||
global LINE
|
||||
assert char == peek(), (LINE, char, peek())
|
||||
skip()
|
||||
|
||||
def emitln(data):
|
||||
emit(data)
|
||||
emit(eol)
|
||||
@ -61,6 +56,11 @@ def lexident():
|
||||
|
||||
return word
|
||||
|
||||
def skipchar(char):
|
||||
global LINE
|
||||
assert char == peek(), (LINE, char, peek())
|
||||
skip()
|
||||
|
||||
def parseconststring():
|
||||
skipchar(quote)
|
||||
emit(quote)
|
||||
@ -364,32 +364,39 @@ def emitheader():
|
||||
emitln("eof = chr(0)")
|
||||
emitln("eol = chr(10)")
|
||||
emitln("quote = chr(34)")
|
||||
emitln("PEEK = None")
|
||||
emitln("LINE = 1")
|
||||
emitln("")
|
||||
emitln("def peek():")
|
||||
emitln(" global PEEK")
|
||||
emitln(" if PEEK is None:")
|
||||
emitln("STDINCOLNO = 0")
|
||||
emitln("STDINLINENO = 1")
|
||||
emitln("STDINPEEK = None")
|
||||
emitln("")
|
||||
emitln("def _readchar():")
|
||||
emitln(" char = sys.stdin.read(1)")
|
||||
emitln(" trace('char', char)")
|
||||
emitln(" if not char:")
|
||||
emitln(" PEEK = eof")
|
||||
emitln(" else:")
|
||||
emitln(" PEEK = char")
|
||||
emitln(" return PEEK")
|
||||
emitln(" return eof")
|
||||
emitln(" return char")
|
||||
emitln("")
|
||||
emitln("peek()")
|
||||
emitln("def peek():")
|
||||
emitln(" return STDINPEEK")
|
||||
emitln("")
|
||||
emitln("def skip():")
|
||||
emitln(" global LINE")
|
||||
emitln(" global PEEK")
|
||||
emitln(" if eol == PEEK:")
|
||||
emitln(" LINE += 1")
|
||||
emitln(" PEEK = None")
|
||||
emitln(" global STDINCOLNO")
|
||||
emitln(" global STDINLINENO")
|
||||
emitln(" global STDINPEEK")
|
||||
emitln(" if eol == STDINPEEK:")
|
||||
emitln(" STDINLINENO += 1")
|
||||
emitln(" STDINCOLNO = 0")
|
||||
emitln(" STDINCOLNO += 1")
|
||||
emitln(" STDINPEEK = _readchar()")
|
||||
emitln("")
|
||||
emitln("def stdinlineno():")
|
||||
emitln(" global STDINLINENO")
|
||||
emitln(" return str(STDINLINENO)")
|
||||
emitln("")
|
||||
emitln("def stdincolno():")
|
||||
emitln(" global STDINCOLNO")
|
||||
emitln(" return str(STDINCOLNO)")
|
||||
emitln("")
|
||||
emitln("def skipchar(char):")
|
||||
emitln(" global LINE")
|
||||
emitln(" assert char == peek(), (LINE, char, peek())")
|
||||
emitln("skip()")
|
||||
emitln("")
|
||||
|
||||
|
||||
@ -1,3 +1,14 @@
|
||||
skipchar exp:
|
||||
declare act
|
||||
declare lineno
|
||||
declare colno
|
||||
calc act peek
|
||||
calc lineno stdinlineno
|
||||
calc colno stdincolno
|
||||
check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno
|
||||
skip
|
||||
/
|
||||
|
||||
emitln data:
|
||||
emit data
|
||||
emit eol
|
||||
@ -430,32 +441,39 @@ emitheader:
|
||||
emitln "eof = chr(0)"
|
||||
emitln "eol = chr(10)"
|
||||
emitln "quote = chr(34)"
|
||||
emitln "PEEK = None"
|
||||
emitln "LINE = 1"
|
||||
emitln ""
|
||||
emitln "def peek():"
|
||||
emitln " global PEEK"
|
||||
emitln " if PEEK is None:"
|
||||
emitln "STDINCOLNO = 0"
|
||||
emitln "STDINLINENO = 1"
|
||||
emitln "STDINPEEK = None"
|
||||
emitln ""
|
||||
emitln "def _readchar():"
|
||||
emitln " char = sys.stdin.read(1)"
|
||||
emitln " trace('char', char)"
|
||||
emitln " if not char:"
|
||||
emitln " PEEK = eof"
|
||||
emitln " else:"
|
||||
emitln " PEEK = char"
|
||||
emitln " return PEEK"
|
||||
emitln " return eof"
|
||||
emitln " return char"
|
||||
emitln ""
|
||||
emitln "peek()"
|
||||
emitln "def peek():"
|
||||
emitln " return STDINPEEK"
|
||||
emitln ""
|
||||
emitln "def skip():"
|
||||
emitln " global LINE"
|
||||
emitln " global PEEK"
|
||||
emitln " if eol == PEEK:"
|
||||
emitln " LINE += 1"
|
||||
emitln " PEEK = None"
|
||||
emitln " global STDINCOLNO"
|
||||
emitln " global STDINLINENO"
|
||||
emitln " global STDINPEEK"
|
||||
emitln " if eol == STDINPEEK:"
|
||||
emitln " STDINLINENO += 1"
|
||||
emitln " STDINCOLNO = 0"
|
||||
emitln " STDINCOLNO += 1"
|
||||
emitln " STDINPEEK = _readchar()"
|
||||
emitln ""
|
||||
emitln "def stdinlineno():"
|
||||
emitln " global STDINLINENO"
|
||||
emitln " return str(STDINLINENO)"
|
||||
emitln ""
|
||||
emitln "def stdincolno():"
|
||||
emitln " global STDINCOLNO"
|
||||
emitln " return str(STDINCOLNO)"
|
||||
emitln ""
|
||||
emitln "def skipchar(char):"
|
||||
emitln " global LINE"
|
||||
emitln " assert char == peek(), (LINE, char, peek())"
|
||||
emitln "skip()"
|
||||
emitln ""
|
||||
/
|
||||
|
||||
@ -1,3 +1,14 @@
|
||||
skipchar exp:
|
||||
declare act
|
||||
declare lineno
|
||||
declare colno
|
||||
calc act peek
|
||||
calc lineno stdinlineno
|
||||
calc colno stdincolno
|
||||
check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno
|
||||
skip
|
||||
/
|
||||
|
||||
emitln data:
|
||||
emit data
|
||||
emit eol
|
||||
@ -273,6 +284,16 @@ parsestatcheck indent:
|
||||
emit indent
|
||||
emitln "{"
|
||||
|
||||
emit " fprintf(stderr, "
|
||||
emit quote
|
||||
emit "%s"
|
||||
emit quote
|
||||
emit ", "
|
||||
emit quote
|
||||
emit "ERROR:"
|
||||
emit quote
|
||||
emitln ");"
|
||||
|
||||
forever
|
||||
skipchar " "
|
||||
|
||||
@ -568,35 +589,55 @@ emitheader:
|
||||
emitln " return 0;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "int LINE = 1;"
|
||||
emitln "int STDINCOLNO = 1;"
|
||||
emitln "int STDINLINENO = 1;"
|
||||
emitln "char * STDINPEEK = 0;"
|
||||
emitln ""
|
||||
emitln "char * peek()"
|
||||
emitln "char * _readchar()"
|
||||
emitln "{"
|
||||
emitln " char * res = malloc(2*sizeof(char));"
|
||||
emitln " res[0] = getc(stdin);"
|
||||
emitln " res[1] = 0;"
|
||||
emitln " ungetc(res[0], stdin);"
|
||||
emitln " return res;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "char * peek()"
|
||||
emitln "{"
|
||||
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read"
|
||||
emitln " return STDINPEEK;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "void skip()"
|
||||
emitln "{"
|
||||
emitln " char c = getc(stdin);"
|
||||
emitln " if( c == 10 ) LINE += 1;"
|
||||
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read, not even peek()'d"
|
||||
emitln " if( STDINPEEK[0] == 10 ) {"
|
||||
emitln " STDINLINENO += 1;"
|
||||
emitln " STDINCOLNO = 0;"
|
||||
emitln " }"
|
||||
emitln " STDINCOLNO += 1;"
|
||||
emitln " STDINPEEK = _readchar();"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "void skipchar(char * chr)"
|
||||
emitln "char * stdinlineno()"
|
||||
emitln "{"
|
||||
emitln " assert(strlen(chr) == 1);"
|
||||
emitln " char * act = peek();"
|
||||
emitln " assert(strlen(act) == 1);"
|
||||
emitln " if( chr[0] == act[0] ) {skip(); return;};"
|
||||
emit " fprintf(stderr, "
|
||||
emitln " char * res = malloc(8*sizeof(char));"
|
||||
emit " sprintf(res, "
|
||||
emit quote
|
||||
emit "Expected '%c' on line %d but saw '%c' instead%c"
|
||||
emit "%d"
|
||||
emit quote
|
||||
emitln ", chr[0], LINE, act[0], 10);"
|
||||
emitln " exit(1);"
|
||||
emitln ", STDINLINENO);"
|
||||
emitln " return res;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "char * stdincolno()"
|
||||
emitln "{"
|
||||
emitln " char * res = malloc(8*sizeof(char));"
|
||||
emit " sprintf(res, "
|
||||
emit quote
|
||||
emit "%d"
|
||||
emit quote
|
||||
emitln ", STDINCOLNO);"
|
||||
emitln " return res;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
return
|
||||
|
||||
@ -151,9 +151,13 @@ Checks stdin for the next character and returns it.
|
||||
|
||||
Advances stdin a single character.
|
||||
|
||||
#### skipchar a
|
||||
#### stdincolno
|
||||
|
||||
Advances stdin a single character, if it matches the first character of `a`. Otherwise, exits the program.
|
||||
Returns the column number for stdin (starting at 1)
|
||||
|
||||
#### stdinlineno
|
||||
|
||||
Returns the line number for stdin (starting at 1)
|
||||
|
||||
### Typing
|
||||
|
||||
|
||||
@ -18,18 +18,18 @@ check: all-it0.results all-it1.results all-it2.results
|
||||
|
||||
all-it0.results: $(addprefix build/,$(addsuffix .it0, $(TESTLIST))) build/builtincheckfalse.it0
|
||||
-rm -f $@
|
||||
echo "Hello" | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success'
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it0 >> $@ ; echo "" >> $@ ;)
|
||||
cat test-input.txt | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success'
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; cat test-input.txt | ./build/$(test).it0 >> $@ ; echo "" >> $@ ;)
|
||||
|
||||
all-it1.results: $(addprefix build/,$(addsuffix .it1, $(TESTLIST))) build/builtincheckfalse.it0
|
||||
all-it1.results: $(addprefix build/,$(addsuffix .it1, $(TESTLIST))) build/builtincheckfalse.it1
|
||||
-rm -f $@
|
||||
echo "Hello" | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success'
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it1 >> $@ ; echo "" >> $@ ;)
|
||||
cat test-input.txt | build/builtincheckfalse.it1 2> /dev/null 2>&1 | grep 'Success'
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; cat test-input.txt | ./build/$(test).it1 >> $@ ; echo "" >> $@ ;)
|
||||
|
||||
all-it2.results: $(addprefix build/,$(addsuffix .it2, $(TESTLIST))) build/builtincheckfalse.it0
|
||||
all-it2.results: $(addprefix build/,$(addsuffix .it2, $(TESTLIST))) build/builtincheckfalse.it2
|
||||
-rm -f $@
|
||||
echo "Hello" | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success'
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it2 >> $@ ; echo "" >> $@ ;)
|
||||
cat test-input.txt | build/builtincheckfalse.it2 2> /dev/null 2>&1 | grep 'Success'
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; cat test-input.txt | ./build/$(test).it2 >> $@ ; echo "" >> $@ ;)
|
||||
|
||||
clean:
|
||||
-rm -f *.results build/*.it0* build/*.it1* build/*.it2*
|
||||
|
||||
86
tests/stdinlineno.lang0
Normal file
86
tests/stdinlineno.lang0
Normal file
@ -0,0 +1,86 @@
|
||||
main:
|
||||
declare char
|
||||
declare colno
|
||||
declare lineno
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char "H" : "Read: H" char
|
||||
check eq colno "1" : "The column number should not have advanced yet" colno
|
||||
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||
skip
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char "e" : "Read: e" char
|
||||
check eq colno "2" : "The column number should have been advanced by 1" colno
|
||||
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||
skip
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char "l" : "Read: l" char
|
||||
check eq colno "3" : "The column number should have been advanced by 2" colno
|
||||
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||
skip
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char "l" : "Read: l" char
|
||||
check eq colno "4" : "The column number should have been advanced by 3" colno
|
||||
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||
skip
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char "o" : "Read: o" char
|
||||
check eq colno "5" : "The column number should have been advanced by 4" colno
|
||||
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||
skip
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char "!" : "Read: !" char
|
||||
check eq colno "6" : "The column number should have been advanced by 5" colno
|
||||
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||
skip
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char eol : "Read: eol" char
|
||||
check eq colno "7" : "The column number should have been advanced by 6" colno
|
||||
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||
skip
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char eol : "Read: eol" char
|
||||
check eq colno "1" : "The column number should have been reset" colno
|
||||
check eq lineno "2" : "The line number should have advanced by 1" lineno
|
||||
skip
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char "T" : "Read: T" char
|
||||
check eq colno "1" : "The column number should have been reset again" colno
|
||||
check eq lineno "3" : "The line number should have advanced by 2" lineno
|
||||
skip
|
||||
|
||||
calc char peek
|
||||
calc colno stdincolno
|
||||
calc lineno stdinlineno
|
||||
check eq char "h" : "Read: h" char
|
||||
check eq colno "2" : "The line number should not have been advanced by 1" colno
|
||||
check eq lineno "3" : "The line number should not have advanced further" lineno
|
||||
|
||||
emit "Success"
|
||||
/
|
||||
3
tests/test-input.txt
Normal file
3
tests/test-input.txt
Normal file
@ -0,0 +1,3 @@
|
||||
Hello!
|
||||
|
||||
This is an example of standard input.
|
||||
Loading…
x
Reference in New Issue
Block a user