Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Parser.ts 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import { EarlyEndOfParseError, NoParsletFoundError } from './errors'
  2. import { Token, TokenType } from './lexer/Token'
  3. import { Lexer } from './lexer/Lexer'
  4. import { InfixParslet, PrefixParslet } from './parslets/Parslet'
  5. import { Grammar } from './grammars/Grammar'
  6. import { assertTerminal } from './assertTypes'
  7. import { Precedence } from './Precedence'
  8. import { TerminalResult } from './result/TerminalResult'
  9. import { IntermediateResult } from './result/IntermediateResult'
  10. export class Parser {
  11. private readonly prefixParslets: PrefixParslet[]
  12. private readonly infixParslets: InfixParslet[]
  13. private readonly lexer: Lexer
  14. constructor (grammar: Grammar, lexer?: Lexer) {
  15. this.lexer = lexer ?? new Lexer()
  16. const {
  17. prefixParslets,
  18. infixParslets
  19. } = grammar
  20. this.prefixParslets = prefixParslets
  21. this.infixParslets = infixParslets
  22. }
  23. parseText (text: string): TerminalResult {
  24. this.lexer.lex(text)
  25. const result = this.parseType(Precedence.ALL)
  26. if (!this.consume('EOF')) {
  27. throw new EarlyEndOfParseError(this.getToken())
  28. }
  29. return result
  30. }
  31. getPrefixParslet (): PrefixParslet | undefined {
  32. return this.prefixParslets.find(p => p.accepts(this.getToken().type, this.peekToken().type))
  33. }
  34. getInfixParslet (precedence: Precedence): InfixParslet | undefined {
  35. return this.infixParslets.find(p => {
  36. return p.getPrecedence() > precedence && p.accepts(this.getToken().type, this.peekToken().type)
  37. })
  38. }
  39. public canParseType (): boolean {
  40. return this.getPrefixParslet() !== undefined
  41. }
  42. public parseType (precedence: Precedence): TerminalResult {
  43. return assertTerminal(this.parseIntermediateType(precedence))
  44. }
  45. public parseIntermediateType (precedence: Precedence): IntermediateResult {
  46. const parslet = this.getPrefixParslet()
  47. if (parslet === undefined) {
  48. throw new NoParsletFoundError(this.getToken())
  49. }
  50. const result = parslet.parsePrefix(this)
  51. return this.parseInfixIntermediateType(result, precedence)
  52. }
  53. public parseInfixIntermediateType (result: IntermediateResult, precedence: Precedence): IntermediateResult {
  54. let parslet = this.getInfixParslet(precedence)
  55. while (parslet !== undefined) {
  56. result = parslet.parseInfix(this, result)
  57. parslet = this.getInfixParslet(precedence)
  58. }
  59. return result
  60. }
  61. public consume (type: TokenType): boolean {
  62. if (this.lexer.token().type !== type) {
  63. return false
  64. }
  65. this.lexer.advance()
  66. return true
  67. }
  68. public getToken (): Token {
  69. return this.lexer.token()
  70. }
  71. public peekToken (): Token {
  72. return this.lexer.peek()
  73. }
  74. public previousToken (): Token | undefined {
  75. return this.lexer.last()
  76. }
  77. getLexer (): Lexer {
  78. return this.lexer
  79. }
  80. }